import winston from 'winston'
import path from 'node:path'
import fs from 'node:fs'
import { app, shell } from 'electron'

// Create mainLogs directory if it doesn't exist
const getLogPath = (): string => {
  // In production, use the same directory as the executable
  // In development, use the project root
  const isProduction = app.isPackaged
  let basePath: string

  if (isProduction) {
    // Get the directory where the executable is located
    basePath = path.dirname(app.getPath('exe'))
  } else {
    // In development, use the project root directory
    basePath = process.env.APP_ROOT || app.getAppPath()
  }

  const logsDir = path.join(basePath, 'mainLogs')

  // Create logs directory if it doesn't exist
  if (!fs.existsSync(logsDir)) {
    try {
      fs.mkdirSync(logsDir, { recursive: true })
    } catch (error) {
      console.error('Failed to create logs directory:', error)
    }
  }

  return logsDir
}

// Get current date in YYYY-MM-DD format for the log filename
const getFormattedDate = (): string => {
  const now = new Date()
  return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
}

// Format timestamp to local time (Beijing time)
const formatLocalTime = (timestamp: Date): string => {
  // 北京时间 = UTC+8
  const localDate = new Date(timestamp.getTime() + 8 * 60 * 60 * 1000)

  const year = localDate.getUTCFullYear()
  const month = String(localDate.getUTCMonth() + 1).padStart(2, '0')
  const day = String(localDate.getUTCDate()).padStart(2, '0')
  const hours = String(localDate.getUTCHours()).padStart(2, '0')
  const minutes = String(localDate.getUTCMinutes()).padStart(2, '0')
  const seconds = String(localDate.getUTCSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

// Configure log file name (app-YYYY-MM-DD.log)
const logFileName = `app-${getFormattedDate()}.log`
const logFilePath = path.join(getLogPath(), logFileName)

// Create a custom format for log entries
const logFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  winston.format.printf(({ timestamp, level, message }) => {
    // 使用本地时间而不是UTC时间
    const localTime = formatLocalTime(new Date())
    return `${localTime} [${level.toUpperCase()}]: ${message}`
  })
)

// Create the logger
export const logger = winston.createLogger({
  level: 'info',
  format: logFormat,
  transports: [
    // Log to the console
    new winston.transports.Console(),
    // Log to a file with rotation
    new winston.transports.File({
      filename: logFilePath,
      maxsize: 10 * 1024 * 1024, // 10MB
      maxFiles: 10,
      tailable: true,
      handleExceptions: true, // 处理异常
    })
  ],
  // 捕获未处理的异常
  exceptionHandlers: [
    new winston.transports.File({
      filename: path.join(getLogPath(), `exceptions-${getFormattedDate()}.log`),
      maxsize: 10 * 1024 * 1024 // 10MB
    })
  ],
  // 不在异常时退出
  exitOnError: false
})

// 处理 pipe 错误
process.on('uncaughtException', (error) => {
  // @ts-ignore
  if (error.code === 'EPIPE') {
    logger.error(`捕获管道断开错误: ${error.message}，但不会终止程序`)
  } else {
    logger.error(`未捕获的异常: ${error.message}\n${error.stack}`)
  }
})

// 全局捕获未处理的Promise拒绝
process.on('unhandledRejection', (reason, promise) => {
  try {
    logger.error(`Unhandled Promise Rejection at: ${promise}\nReason: ${reason}`)
  } catch (error) {
    // 忽略日志记录错误，避免无限循环
  }
})

// 保存原始 console 方法
const originalConsole = {
  log: console.log,
  info: console.info,
  warn: console.warn,
  error: console.error,
  debug: console.debug
}

// 安全日志函数，捕获所有可能的日志错误
const safeLog = (logFn: Function, ...args: any[]) => {
  try {
    return logFn(...args)
  } catch (error) {
    // 如果是管道断开错误，静默失败
    if (error && (error as any).code === 'EPIPE') {
      return
    }

    // 尝试使用原始控制台记录错误，但不抛出异常
    try {
      originalConsole.error('日志记录失败:', error)
    } catch (e) {
      // 完全静默失败
    }
  }
}

// Replace console methods with our logging functions
console.log = (...args: any[]) => {
  safeLog(originalConsole.log, ...args)

  try {
    const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ')
    logger.info(message)
  } catch (error) {
    // 忽略日志错误
  }
}

console.info = (...args: any[]) => {
  safeLog(originalConsole.info, ...args)

  try {
    const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ')
    logger.info(message)
  } catch (error) {
    // 忽略日志错误
  }
}

console.warn = (...args: any[]) => {
  safeLog(originalConsole.warn, ...args)

  try {
    const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ')
    logger.warn(message)
  } catch (error) {
    // 忽略日志错误
  }
}

console.error = (...args: any[]) => {
  safeLog(originalConsole.error, ...args)

  try {
    const message = args.map(arg => {
      if (arg instanceof Error) {
        return `${arg.message}\n${arg.stack}`
      }
      return typeof arg === 'object' ? JSON.stringify(arg) : arg
    }).join(' ')
    logger.error(message)
  } catch (error) {
    // 忽略日志错误
  }
}

console.debug = (...args: any[]) => {
  safeLog(originalConsole.debug, ...args)

  try {
    const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg).join(' ')
    logger.debug(message)
  } catch (error) {
    // 忽略日志错误
  }
}

// Add system info to log at startup
export function logSystemInfo() {
  try {
    logger.info('---------- Application Started ----------')
    logger.info(`App Name: ${app.getName()}`)
    logger.info(`App Version: ${app.getVersion()}`)
    logger.info(`Electron Version: ${process.versions.electron}`)
    logger.info(`Chrome Version: ${process.versions.chrome}`)
    logger.info(`Node Version: ${process.versions.node}`)
    logger.info(`Platform: ${process.platform} (${process.arch})`)
    logger.info(`Log Path: ${logFilePath}`)
    logger.info(`env: ${import.meta.env.MODE}`)
    logger.info('----------------------------------------')
  } catch (error) {
    // 忽略日志错误
  }
}

// Log when application is about to exit
export function logShutdown() {
  try {
    logger.info('---------- Application Shutting Down ----------')
  } catch (error) {
    // 忽略日志错误
  }
}

// 打开日志目录
export function openLogsDirectory() {
  const logsDir = getLogPath()

  if (fs.existsSync(logsDir)) {
    shell.openPath(logsDir)
    return { success: true, path: logsDir }
  } else {
    return { success: false, error: '日志目录不存在' }
  }
}

// 导出日志路径获取方法，方便其他模块使用
export { getLogPath, logFilePath }
